﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entities;
using System.Data.SqlClient;

namespace AccesoDatos
{
    public class Productos
    {
        public static void Insertar(Producto p, out int sFilasAfectadas)
        {
            try
            {
                sFilasAfectadas = 0;

                if (p.IdProducto == 0)
                {
                    //alta

                    SqlConnection conexion = DB.Conectar();

                    string comando = "INSERT INTO Producto (nombre, idMarca, idCategoria, tamanio, idUnidadMedida, precioUnitario, stock, fechaIngreso) VALUES (@nombre,@idMarca,@idCategoria,@tamanio,@idUnidadMedida,@precioUnitario,@stock,@fechaIngreso)";
                    List<SqlParameter> lstParametros = new List<SqlParameter>();
                    lstParametros.Add(new SqlParameter("@nombre", p.Nombre));
                    lstParametros.Add(new SqlParameter("@idMarca", p.IdMarca));
                    lstParametros.Add(new SqlParameter("@idCategoria", p.IdCategoria));
                    lstParametros.Add(new SqlParameter("@tamanio", p.Tamanio));
                    lstParametros.Add(new SqlParameter("@idUnidadMedida", p.IdUnidadMedida));
                    lstParametros.Add(new SqlParameter("@precioUnitario", p.PrecioUnitario));
                    lstParametros.Add(new SqlParameter("@stock", p.Stock));
                    lstParametros.Add(new SqlParameter("@fechaIngreso", p.FechaIngreso));

                    int filas = DB.EjecutarCommand(comando, lstParametros, conexion);

                    if (filas > 0)
                        sFilasAfectadas = filas;
                }
                else
                {
                    //Modificar 
                    SqlConnection conexion = DB.Conectar();
                    string comando = "UPDATE  Producto SET nombre = @nombre, idMarca = @idMarca, idCategoria = @idCategoria, tamanio = @tamanio, idUnidadMedida = @idUnidadMedida, precioUnitario = @precioUnitario, stock = @stock WHERE (idProducto = @idProducto)";

                    List<SqlParameter> lstParametros = new List<SqlParameter>();
                    lstParametros.Add(new SqlParameter("@nombre", p.Nombre));
                    lstParametros.Add(new SqlParameter("@idMarca", p.IdMarca));
                    lstParametros.Add(new SqlParameter("@idCategoria", p.IdCategoria));
                    lstParametros.Add(new SqlParameter("@tamanio", p.Tamanio));
                    lstParametros.Add(new SqlParameter("@idUnidadMedida", p.IdUnidadMedida));
                    lstParametros.Add(new SqlParameter("@precioUnitario", p.PrecioUnitario));
                    lstParametros.Add(new SqlParameter("@stock", p.Stock));
                    lstParametros.Add(new SqlParameter("@fechaIngreso", p.FechaIngreso));

                    int filas = DB.EjecutarCommand(comando, lstParametros, conexion);
                    if (filas > 0)
                        sFilasAfectadas = filas;
                }
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al procesar el producto.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al procesar el producto.", ex);
            }
        }
        public static void Eliminar(int idProducto, out int afectadas)
        {            
            try
            {
                SqlConnection conexion = DB.Conectar();
                string comando = "DELETE FROM Producto WHERE  (idProducto = @id)";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                lstParametros.Add(new SqlParameter("@id", idProducto));
                afectadas = DB.EjecutarCommand(comando, lstParametros, conexion);
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al eliminar el producto.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al eliminar el producto.", ex);
            }            

        }
        public static int ObtenerStockProducto(int idProd)
        {
            int stockActual = 0;
            SqlConnection conexion = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT stock FROM Producto WHERE idProducto = @id";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                lstParametros.Add(new SqlParameter("@id", idProd));
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                while (dr.Read())
                {
                    stockActual = (int)dr["stock"];
                }
                //conexion.Close();
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al obtener el stock.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al obtener el stock.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return stockActual;

        }
        public static List<Producto> ObtenerTodos()
        {
            List<Producto> lstProductos = null;
            SqlConnection conexion = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT idProducto,nombre,idMarca,idCategoria,tamanio,idUnidadMedida,stock, preciounitario FROM Producto";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //List<Producto> lstProductos = new List<Producto>();
                lstProductos = new List<Producto>();
                Producto objProducto;
                while (dr.Read())
                {
                    objProducto = new Producto();
                    objProducto.IdProducto = (int)dr["idProducto"];
                    objProducto.IdMarca = (int)dr["idMarca"];
                    objProducto.IdCategoria = (int)dr["idCategoria"];
                    objProducto.Nombre = dr["nombre"].ToString();
                    objProducto.Tamanio = (float)Convert.ToDouble(dr["tamanio"]);
                    objProducto.IdUnidadMedida = (int)dr["idUnidadMedida"];
                    objProducto.Stock = (int)dr["stock"];
                    objProducto.PrecioUnitario = (float)Convert.ToDouble(dr["precioUnitario"]);
                    lstProductos.Add(objProducto);
                    objProducto = null;
                }
                //conexion.Close();

            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return lstProductos;
        }
        public static Producto BuscarPorId(int idProd)
        {
            Producto objProducto = null;
            SqlConnection conexion = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT idProducto,nombre,idMarca,idCategoria,tamanio,idUnidadMedida,precioUnitario,stock FROM Producto Where idProducto = @id";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                lstParametros.Add(new SqlParameter("@id", idProd));
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //Producto objProducto = null;
                while (dr.Read())
                {
                    objProducto = new Producto();
                    objProducto.IdProducto = (int)dr["idProducto"];
                    objProducto.Nombre = dr["nombre"].ToString();
                    objProducto.IdMarca = (int)dr["idMarca"];
                    objProducto.IdCategoria = (int)dr["idCategoria"];
                    objProducto.Tamanio = (float)Convert.ToDouble(dr["tamanio"]);
                    objProducto.IdUnidadMedida = (int)dr["idUnidadMedida"];
                    objProducto.PrecioUnitario = (float)Convert.ToDouble(dr["precioUnitario"]);
                    objProducto.Stock = (int)dr["stock"];
                }
                //conexion.Close();
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar el producto.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar el producto.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return objProducto;
        }
        public static List<Producto> ObtenerTodos(int? idMarca, int? idCategoria, DateTime? fechaDesde, DateTime? fechaHasta)
        {
            List<Producto> lstProductosCompletos = null; //este es el filtrado
            try
            {
                bool hayMarca = false, hayCategoria = false;
                if (idMarca != null)
                    hayMarca = true;
                if (idCategoria != null)
                    hayCategoria = true;
                List<Producto> lstProductos = null;
//                List<Producto> lstProductosCompletos = null; //este es el filtrado
                Facturas facturas = new Facturas();
                List<Factura> lstFacturasPeriodo = facturas.obtenerFacturasPorFecha(fechaDesde, fechaHasta);
                DetallesFactura detalles = new DetallesFactura();
                if (lstFacturasPeriodo != null && lstFacturasPeriodo.Count > 0)
                    lstProductos = detalles.ObtenerCantidadVendidaProductos(lstFacturasPeriodo);
                else
                    lstProductos = detalles.ObtenerCantidadVendidaProductos();

                if (lstProductos != null && lstProductos.Count > 0)
                {
                    lstProductosCompletos = new List<Producto>();
                    Producto prod = null;
                    foreach (Producto item in lstProductos)
                    {
                        prod = new Producto();
                        prod = BuscarPorId(item.IdProducto);
                        prod.CantVendida = item.CantVendida;
                        //validamos para ver hay que insertarlo o no
                        if (hayMarca && prod.IdMarca == idMarca && hayCategoria && idCategoria == prod.IdCategoria) //estan los dos y coinciden
                            lstProductosCompletos.Add(prod);
                        else if (!hayMarca && hayCategoria && idCategoria == prod.IdCategoria) //solo hay categoria y coincide
                            lstProductosCompletos.Add(prod);
                        else if (!hayCategoria && hayMarca && idMarca == prod.IdMarca)  //solo hay marca y coincide
                            lstProductosCompletos.Add(prod);
                        else if (!hayMarca && !hayCategoria)  //no hay ni marca ni categoria
                            lstProductosCompletos.Add(prod);
                        prod = null;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar al cargar los productos.", ex);
            }
            
            return lstProductosCompletos;
        }

        public static List<Producto> ObtenerTodos(string nombre, int? idProd)
        {
            List<Producto> lstProductos = null;
            SqlConnection conexion = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT idProducto,nombre,idMarca,idCategoria,tamanio,idUnidadMedida,stock,precioUnitario FROM Producto WHERE 1=1";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                if (!string.IsNullOrEmpty(nombre))
                {
                    comando += " and nombre like @nombre";
                    lstParametros.Add(new SqlParameter("@nombre", '%' + nombre + '%'));
                }

                if (idProd != null)
                {
                    comando += " and idProducto = @idProd";
                    lstParametros.Add(new SqlParameter("@idProd", idProd));
                }
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //List<Producto> lstProductos = new List<Producto>();
                lstProductos = new List<Producto>();
                Producto objProducto;
                while (dr.Read())
                {
                    objProducto = new Producto();
                    objProducto.IdProducto = (int)dr["idProducto"];
                    objProducto.Nombre = dr["nombre"].ToString();
                    objProducto.IdMarca = (int)dr["idMarca"];
                    objProducto.IdCategoria = (int)dr["idCategoria"];
                    objProducto.Tamanio = (float)Convert.ToDouble(dr["tamanio"]);
                    objProducto.IdUnidadMedida = (int)dr["idUnidadMedida"];
                    objProducto.Stock = (int)dr["stock"];
                    objProducto.PrecioUnitario = (float)Convert.ToDouble(dr["precioUnitario"]);
                    lstProductos.Add(objProducto);
                    objProducto = null;
                }
                //conexion.Close();
                //return lstProductos;
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return lstProductos;
        }
        public static List<Producto> ObtenerTodosInforme(int? idMarca, int? idCategoria, DateTime? fechaDesde, DateTime? fechaHasta)
        {
            bool hayMarca = false, hayCategoria = false;
            if (idMarca != null)
                hayMarca = true;
            if (idCategoria != null)
                hayCategoria = true;
            List<Producto> lstProductos = null;
            List<Producto> lstProductosCompletos = null; //este es el filtrado
            Facturas facturas = new Facturas();
            List<Factura> lstFacturasPeriodo = facturas.obtenerFacturasPorFecha(fechaDesde, fechaHasta);
            DetallesFactura detalles = new DetallesFactura();
            if (lstFacturasPeriodo != null && lstFacturasPeriodo.Count > 0)
                lstProductos = detalles.ObtenerCantidadVendidaProductos(lstFacturasPeriodo);
            else
                lstProductos = detalles.ObtenerCantidadVendidaProductos();

            if (lstProductos != null && lstProductos.Count > 0)
            {
                lstProductosCompletos = new List<Producto>();
                Producto prod = null;
                foreach (Producto item in lstProductos)
                {
                    prod = new Producto();
                    prod = BuscarPorId(item.IdProducto);
                    prod.CantVendida = item.CantVendida;
                    //validamos para ver hay que insertarlo o no
                    if (hayMarca && prod.IdMarca == idMarca && hayCategoria && idCategoria == prod.IdCategoria) //estan los dos y coinciden
                        lstProductosCompletos.Add(prod);
                    else if (!hayMarca && hayCategoria && idCategoria == prod.IdCategoria) //solo hay categoria y coincide
                        lstProductosCompletos.Add(prod);
                    else if (!hayCategoria && hayMarca && idMarca == prod.IdMarca)  //solo hay marca y coincide
                        lstProductosCompletos.Add(prod);
                    else if (!hayMarca && !hayCategoria)  //no hay ni marca ni categoria
                        lstProductosCompletos.Add(prod);
                    prod = null;
                }
            }
            return lstProductosCompletos;
        }
        public static List<Producto> ObtenerTodos(string nombre, int? idProd, string criterio, string direccion)
        {
            List<Producto> lstProductos = null;
            SqlConnection conexion = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT idProducto,nombre,idMarca,idCategoria,tamanio,idUnidadMedida,stock,precioUnitario FROM Producto WHERE 1=1";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                if (!string.IsNullOrEmpty(nombre))
                {
                    comando += " and nombre like @nombre";
                    lstParametros.Add(new SqlParameter("@nombre", '%' + nombre + '%'));
                }

                if (idProd != null)
                {
                    comando += " and idProducto = @idProd";
                    lstParametros.Add(new SqlParameter("@idProd", idProd));
                }
                comando += " order by " + criterio + " " + direccion;
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //List<Producto> lstProductos = new List<Producto>();
                lstProductos = new List<Producto>();
                Producto objProducto;
                while (dr.Read())
                {
                    objProducto = new Producto();
                    objProducto.IdProducto = (int)dr["idProducto"];
                    objProducto.Nombre = dr["nombre"].ToString();
                    objProducto.IdMarca = (int)dr["idMarca"];
                    objProducto.IdCategoria = (int)dr["idCategoria"];
                    objProducto.Tamanio = (float)Convert.ToDouble(dr["tamanio"]);
                    objProducto.IdUnidadMedida = (int)dr["idUnidadMedida"];
                    objProducto.Stock = (int)dr["stock"];
                    objProducto.PrecioUnitario = (float)Convert.ToDouble(dr["precioUnitario"]);
                    lstProductos.Add(objProducto);
                    objProducto = null;
                }
                //conexion.Close();
                //return lstProductos;
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return lstProductos;
        }
        public static List<Producto> ObtenerTodosOrdenados(string criterio, string direccion)
        {
            List<Producto> lstProductos = null;
            SqlConnection conexion = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT idProducto,nombre,idMarca,idCategoria,tamanio,idUnidadMedida,stock, preciounitario FROM Producto order by " + criterio + " " + direccion;
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //List<Producto> lstProductos = new List<Producto>();
                lstProductos = new List<Producto>();
                Producto objProducto;
                while (dr.Read())
                {
                    objProducto = new Producto();
                    objProducto.IdProducto = (int)dr["idProducto"];
                    objProducto.IdMarca = (int)dr["idMarca"];
                    objProducto.IdCategoria = (int)dr["idCategoria"];
                    objProducto.Nombre = dr["nombre"].ToString();
                    objProducto.Tamanio = (float)Convert.ToDouble(dr["tamanio"]);
                    objProducto.IdUnidadMedida = (int)dr["idUnidadMedida"];
                    objProducto.Stock = (int)dr["stock"];
                    objProducto.PrecioUnitario = (float)Convert.ToDouble(dr["precioUnitario"]);
                    lstProductos.Add(objProducto);
                    objProducto = null;
                }
                //conexion.Close();

            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar los productos.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return lstProductos;
        }
    }
}
